#pragma once

#include <zenoui/check_gl.hpp>
#include <zenox/pragma.hpp>
#include <zenox/memory.hpp>

namespace zenoui {

struct Event;
struct Widget;
struct FontCache;

struct Game {
private:
    struct Private;
    std::unique_ptr<Private> m_private;

    Game();
    ~Game();
    Game(Game &&) = delete;

public:
    static Game &instance();

    ZENO_CONST_FN GLFWwindow *get_glfw_window() const;
    ZENO_CONST_FN FontCache *get_font_cache() const;

    bool init
    ( int version = 20
    , int width = 1024
    , int height = 768
    , int numsamples = 4
    , int framerate = 60
    , bool fullscreen = false
    , bool osmesa = false
    );
    void show_win();
    bool main_loop();
    Widget *set_root_widget(zenox::shared_ptr<Widget> widget);

protected:
    void setup_gl();
    void render_gl();

private:
    void cursor_pos_callback(double xpos, double ypos);
    void mouse_button_callback(int button, int action, int mods);
    void scroll_callback(double xoffset, double yoffset);
    void key_callback(int key, int scancode, int action, int mods);
    void char_callback(unsigned codeprint);
    void drop_callback(int count, const char **paths);
    void framebuffer_size_callback(int width, int height);

    zenox::weak_ptr<Widget> dispatch_event_to_child(Event *event);
    void set_glfw_window(GLFWwindow *window);
};

}
